package com.epfuse.cloud.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.epfuse.cloud.admin.api.entity.SysDict;
import com.epfuse.cloud.admin.api.entity.SysRole;
import com.epfuse.cloud.admin.api.entity.SysRoleMenu;
import com.epfuse.cloud.admin.api.vo.RoleExcelVO;
import com.epfuse.cloud.admin.mapper.SysRoleMapper;
import com.epfuse.cloud.admin.mapper.SysRoleMenuMapper;
import com.epfuse.cloud.admin.service.SysRoleService;
import com.epfuse.cloud.common.core.constant.CacheConstants;
import com.epfuse.cloud.common.core.exception.ErrorCodes;
import com.epfuse.cloud.common.core.util.MsgUtils;
import com.epfuse.cloud.common.core.util.R;
import com.pig4cloud.plugin.excel.vo.ErrorMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author : 孙峰
 * @Description: 部门管理 服务实现类
 * @Date : 2022/7/20  9:37
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    private final SysRoleMenuMapper sysRoleMenuMapper;

    /**
     * 通过角色ID，删除角色,并清空角色菜单缓存
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CacheConstants.MENU_DETAILS, allEntries = true)
    public Boolean removeRoleById(Long id) {
        sysRoleMenuMapper.delete(Wrappers.<SysRoleMenu>update().lambda().eq(SysRoleMenu::getRoleId, id));
        return this.removeById(id);
    }

    /**
     * 导入角色
     *
     * @param excelVOList   角色列表
     * @param bindingResult 错误信息列表
     * @return ok fail
     */
    @Override
    public R importRole(List<RoleExcelVO> excelVOList, BindingResult bindingResult) {
        // 通用校验获取失败的数据
        List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();

        // 个性化校验逻辑
        List<SysRole> roleList = this.list();

        // 执行数据插入操作 组装 RoleDto
        for (int i = 0; i < excelVOList.size(); i++) {
            RoleExcelVO excel = excelVOList.get(i);
            Set<String> errorMsg = new HashSet<>();
            // 检验角色名称或者角色编码是否存在
            boolean existRole = roleList.stream().anyMatch(sysRole -> excel.getRoleName().equals(sysRole.getRoleName())
                    || excel.getRoleCode().equals(sysRole.getRoleCode()));

            if (existRole) {
                errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_ROLE_NAMEORCODE_EXISTING, excel.getRoleName(),
                        excel.getRoleCode()));
            }

            // 数据合法情况
            if (CollUtil.isEmpty(errorMsg)) {
                insertExcelRole(excel);
            } else {
                // 数据不合法情况
                errorMessageList.add(new ErrorMessage((long) (i + 2), errorMsg));
            }
        }
        if (CollUtil.isNotEmpty(errorMessageList)) {
            return R.failed(errorMessageList);
        }
        return R.ok();
    }

    /**
     * 查询全部的角色
     *
     * @return list
     */
    @Override
    public List<RoleExcelVO> listRole() {
        List<SysRole> roleList = this.list(Wrappers.emptyWrapper());

        List<RoleExcelVO> collect = roleList.stream().map(sysRole -> {
            RoleExcelVO roleExcelVO = new RoleExcelVO();
            BeanUtil.copyProperties(sysRole, roleExcelVO);
            return roleExcelVO;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public IPage<SysRole> page(Page page, SysRole sysRole) {
        LambdaQueryWrapper<SysRole> lambdaQuery = Wrappers.lambdaQuery(SysRole.class);
        if (ObjectUtil.isNotEmpty(sysRole.getParams())) {
            Map<String, Object> params = sysRole.getParams();
            if (ObjectUtil.isNotEmpty(params.get("beginTime"))) {
                lambdaQuery.ge(SysRole::getCreateTime, params.get("beginTime"));
            }
            if (ObjectUtil.isNotEmpty(params.get("endTime"))) {
                lambdaQuery.le(SysRole::getCreateTime, params.get("endTime"));
            }
        }
        if (ObjectUtil.isNotEmpty(sysRole.getRoleName())) {
            lambdaQuery.like(SysRole::getRoleName, sysRole.getRoleName());
        }
        if (ObjectUtil.isNotEmpty(sysRole.getRoleCode())) {
            lambdaQuery.like(SysRole::getRoleCode, sysRole.getRoleCode());
        }
        if (ObjectUtil.isNotEmpty(sysRole.getStatus())) {
            lambdaQuery.eq(SysRole::getStatus, sysRole.getStatus());
        }
        return page(page, lambdaQuery);
    }

    /**
     * 插入excel Role
     */
    private void insertExcelRole(RoleExcelVO excel) {
        SysRole sysRole = new SysRole();
        sysRole.setRoleName(excel.getRoleName());
        sysRole.setRoleDesc(excel.getRoleDesc());
        sysRole.setRoleCode(excel.getRoleCode());
        this.save(sysRole);
    }
}
